#include "serverhelper.h"
#include <QCryptographicHash>
#include <QUrlQuery>

namespace WordMemory
{
    ServerHelper::ServerHelper(QObject *parent)
        : QObject(parent)
        , manager(new QNetworkAccessManager(this))
    {}

    /*
     * 用户接口
     ***/

    void ServerHelper::login(const QString &username, const QString &password)
    {
        QJsonObject data;
        data["username"] = username;
        data["password"] = password;

        sendPostRequest("/api/user/login", data, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            User user;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    user = User::fromJson(json["data"].toObject());
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit loginFinished(success, user, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::registerUser(const QString &username, const QString &password, const QString &real_name)
    {
        QJsonObject data;
        data["username"] = username;
        data["password"] = password;
        data["real_name"] = real_name;

        sendPostRequest("/api/user/register", data, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            User user;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    user = User::fromJson(json["data"].toObject());
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit registerFinished(success, user, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::getUser(int userId)
    {
        QUrlQuery query;
        query.addQueryItem("id", QString::number(userId));

        sendGetRequest("/api/user", query, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            User user;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    user = User::fromJson(json["data"].toObject());
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit getUserFinished(success, user, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::updateUser(int userId, const QString &realName)
    {
        QJsonObject data;
        data["id"] = userId;
        data["real_name"] = realName;

        sendPutRequest("/api/user", data, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            User user;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    user = User::fromJson(json["data"].toObject());
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit updateUserFinished(success, user, error);
            reply->deleteLater();
        });
    }

    /*
     * 单词接口
     ***/

    void ServerHelper::getWord(int userId, const QString &word)
    {
        QUrlQuery query;
        query.addQueryItem("user_id", QString::number(userId));
        query.addQueryItem("word", word);

        sendGetRequest("/api/words", query, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            Word word;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    word = Word::fromJson(json["data"].toObject());
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit getWordFinished(success, word, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::addCustomExample(int wordId, const QString &example, const QString &translation)
    {
        QJsonObject data;
        data["word_id"] = wordId;
        data["example"] = example;
        data["translation"] = translation;

        sendPostRequest("/api/words/custom/example", data, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit addCustomExampleFinished(success, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::addCustomMnemonic(int wordId, const QString &mnemonic)
    {
        QJsonObject data;
        data["word_id"] = wordId;
        data["mnemonic"] = mnemonic;

        sendPostRequest("/api/words/custom/mnemonic", data, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit addCustomMnemonicFinished(success, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::updateWordStatus(int userId, int wordId, const QString &status)
    {
        QJsonObject data;
        data["user_id"] = userId;
        data["word_id"] = wordId;
        data["status"] = status;

        sendPostRequest("/api/words/status", data, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit updateWordStatusFinished(success, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::addWordToFavorites(int userId, int wordId)
    {
        QJsonObject data;
        data["user_id"] = userId;
        data["word_id"] = wordId;

        sendPostRequest("/api/vocabularies/favorites/add", data, [this, wordId](QNetworkReply *reply) {
            QString error;
            bool success = false;
            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200 || json["code"].toInt() == 201) { // Backend might return 200 or 201
                    success = true;
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
                qDebug() << "Add to Fav Error: " << reply->readAll();
            }
            emit addWordToFavoritesFinished(success, wordId, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::removeWordFromFavorites(int userId, int wordId)
    {
        QJsonObject data;
        data["user_id"] = userId;
        data["word_id"] = wordId;

        // Backend uses POST for remove: /api/vocabularies/favorites/remove
        sendPostRequest("/api/vocabularies/favorites/remove", data, [this, wordId](QNetworkReply *reply) {
            QString error;
            bool success = false;
            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) { // Or 204 if backend sends No Content
                    success = true;
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
                qDebug() << "Remove from Fav Error: " << reply->readAll();
            }
            emit removeWordFromFavoritesFinished(success, wordId, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::addWordToMistakesBook(int userId, int wordId)
    {
        QJsonObject data;
        data["user_id"] = userId;
        data["word_id"] = wordId;
        sendPostRequest("/api/vocabularies/mistakes/add", data, [this, wordId](QNetworkReply *reply) {
            QString error;
            bool success = false;
            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200 || json["code"].toInt() == 201) {
                    success = true;
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
                qDebug() << "Add to Mistakes Book Error: " << reply->readAll();
            }
            emit addWordToMistakesBookFinished(success, wordId, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::removeWordFromMistakesBook(int userId, int wordId)
    {
        QJsonObject data;
        data["user_id"] = userId;
        data["word_id"] = wordId;
        sendPostRequest("/api/vocabularies/mistakes/remove", data, [this, wordId](QNetworkReply *reply) {
            // ... (similar error handling and signal emission) ...
            QString error_msg; // Renamed
            bool success_flag = false; // Renamed
            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success_flag = true;
                } else {
                    error_msg = json["message"].toString();
                }
            } else {
                error_msg = reply->errorString();
            }
            emit removeWordFromMistakesBookFinished(success_flag, wordId, error_msg);
            reply->deleteLater();
        });
    }


    /*
     * 词库接口
     ***/

    void ServerHelper::getVocabularies(int userId)
    {
        QUrlQuery query;
        query.addQueryItem("user_id", QString::number(userId));

        sendGetRequest("/api/vocabularies", query, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            QList<Vocabulary> vocabularies;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    QJsonArray data = json["data"].toArray();
                    for (const auto &item : data) {
                        vocabularies.append(Vocabulary::fromJson(item.toObject()));
                    }
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit getVocabulariesFinished(success, vocabularies, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::addVocabulary(int userId, const QString &name)
    {
        QJsonObject data;
        data["user_id"] = userId;
        data["name"] = name;

        sendPostRequest("/api/vocabularies", data, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            Vocabulary vocabulary;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    vocabulary = Vocabulary::fromJson(json["data"].toObject());
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit addVocabularyFinished(success, vocabulary, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::getWordsByVocabularyId(int userId, int vocabularyId)
    {
        QUrlQuery query;
        query.addQueryItem("user_id", QString::number(userId));

        sendGetRequest("/api/vocabularies/" + QString::number(vocabularyId) + "/words", query, [this, vocabularyId](QNetworkReply *reply) {
            QString error;
            bool success = false;
            QList<Word> words;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    QJsonArray data = json["data"].toArray();
                    for (const auto &item : data) {
                        words.append(Word::fromJson(item.toObject()));
                    }
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit getWordsByVocabularyIdFinished(success, vocabularyId, words, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::getDefaultVocabulary(int userId)
    {
        QUrlQuery query;
        query.addQueryItem("user_id", QString::number(userId));

        sendGetRequest("/api/vocabularies/default", query, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            Vocabulary vocabulary;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    vocabulary = Vocabulary::fromJson(json["data"].toObject());
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit getDefaultVocabularyFinished(success, vocabulary, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::setDefaultVocabulary(int userId, int vocabularyId)
    {
        QJsonObject data;
        data["user_id"] = userId;
        data["vocabulary_id"] = vocabularyId;

        sendPostRequest("/api/vocabularies/default", data, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }

            emit setDefaultVocabularyFinished(success, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::getMistakesBookWords(int userId)
    {
        QUrlQuery query;
        query.addQueryItem("user_id", QString::number(userId));
        sendGetRequest("/api/vocabularies/mistakes/words", query, [this](QNetworkReply *reply) {
            // ... (parse QList<Word> and emit getMistakesBookWordsFinished) ...
            QString error_msg;
            bool success_flag = false;
            QList<Word> words_list;
            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success_flag = true;
                    QJsonArray dataArray = json["data"].toArray();
                    for(const auto& item : dataArray) {
                        words_list.append(Word::fromJson(item.toObject()));
                    }
                } else {
                    error_msg = json["message"].toString();
                }
            } else {
                error_msg = reply->errorString();
            }
            emit getMistakesBookWordsFinished(success_flag, words_list, error_msg);
            reply->deleteLater();
        });
    }

    /*
     * 学习统计接口
     ***/

    void ServerHelper::getLearningStats(int userId)
    {
        QUrlQuery query;
        query.addQueryItem("user_id", QString::number(userId));

        sendGetRequest("/api/stats/learning", query, [this](QNetworkReply *reply) {
            QString error;
            bool success = false;
            QJsonObject stats;

            if (reply->error() == QNetworkReply::NoError) {
                QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                QJsonObject json = doc.object();
                if (json["code"].toInt() == 200) {
                    success = true;
                    stats = json["data"].toObject();
                } else {
                    error = json["message"].toString();
                }
            } else {
                error = reply->errorString();
            }
            emit getLearningStatsFinished(success, stats, error);
            reply->deleteLater();
        });
    }

    void ServerHelper::getDailyLearningSummary(int userId, int days)
    {
        QUrlQuery query;
        query.addQueryItem("user_id", QString::number(userId));
        query.addQueryItem("days", QString::number(days));

        sendGetRequest("/api/stats/daily-summary", query, [this](QNetworkReply *reply) {
            QString error_str; // Renamed to avoid conflict with ServerHelper member
            bool success_flag = false; // Renamed
            QJsonArray summary_array;

            if (reply->error() == QNetworkReply::NoError) {
                QByteArray response_data = reply->readAll();
                QJsonDocument doc = QJsonDocument::fromJson(response_data);
                QJsonObject json = doc.object();

                // qDebug() << "Raw daily summary response:" << response_data;

                if (json["code"].toInt() == 200) {
                    if (json["data"].isArray()) {
                        success_flag = true;
                        summary_array = json["data"].toArray();
                    } else {
                        error_str = "Invalid data format: 'data' is not an array.";
                        qDebug() << "ServerHelper Error:" << error_str << "Response:" << response_data;
                    }
                } else {
                    error_str = json["message"].toString("Unknown error from server");
                    qDebug() << "ServerHelper Error:" << error_str << "Code:" << json["code"].toInt() << "Response:" << response_data;
                }
            } else {
                error_str = reply->errorString();
                qDebug() << "ServerHelper Network Error:" << error_str << "Details:" << reply->readAll();
            }
            emit getDailyLearningSummaryFinished(success_flag, summary_array, error_str);
            reply->deleteLater();
        });
    }

    /*
     * 社区接口
     ***/

    void ServerHelper::getCommunityPosts(int currentUserId)
    {
        QUrlQuery query;
        if (currentUserId > 0) {
            query.addQueryItem("user_id", QString::number(currentUserId));
        }

        sendGetRequest("/api/community/posts", query, [this](QNetworkReply *reply) {
                QString error;
                bool success = false;
                QList<CommunityPost> postsList;

                if (reply->error() == QNetworkReply::NoError) {
                    QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                    QJsonObject json = doc.object();
                    if (json["code"].toInt() == 200) {
                        success = true;
                        QJsonArray dataArray = json["data"].toArray();
                        for (const QJsonValue &val : dataArray) {
                            postsList.append(CommunityPost::fromJson(val.toObject()));
                        }
                    } else {
                        error = json["message"].toString();
                    }
                } else {
                    error = reply->errorString();
                }
                emit getCommunityPostsFinished(success, postsList, error);
                reply->deleteLater();
            });
    }

    void ServerHelper::getCommunityPostDetails(int postId, int currentUserId) {
        QUrlQuery query;
         if (currentUserId > 0) {
            query.addQueryItem("user_id", QString::number(currentUserId));
        }
        sendGetRequest(QString("/api/community/posts/%1").arg(postId), query,
            [this](QNetworkReply *reply) {
                QString error;
                bool success = false;
                CommunityPost post;
                if (reply->error() == QNetworkReply::NoError) {
                    QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                    QJsonObject json = doc.object();
                    if (json["code"].toInt() == 200) {
                        success = true;
                        post = CommunityPost::fromJson(json["data"].toObject());
                    } else {
                        error = json["message"].toString();
                    }
                } else {
                    error = reply->errorString();
                }
                emit getCommunityPostDetailsFinished(success, post, error);
                reply->deleteLater();
            });
    }

    void ServerHelper::toggleLikePost(int postId, int userId) {
        QJsonObject data;
        data["user_id"] = userId;
        sendPostRequest(QString("/api/community/posts/%1/toggle_like").arg(postId), data,
            [this, postId](QNetworkReply *reply) {
                QString error;
                bool success = false;
                int newLikes = 0;
                bool likedByMe = false;

                if (reply->error() == QNetworkReply::NoError) {
                    QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                    QJsonObject json = doc.object();
                    if (json["code"].toInt() == 200) {
                        success = true;
                        QJsonObject dataObj = json["data"].toObject();
                        newLikes = dataObj["likes_count"].toInt();
                        likedByMe = dataObj["is_liked_by_current_user"].toBool();
                    } else {
                        error = json["message"].toString();
                    }
                } else {
                    error = reply->errorString();
                }
                emit toggleLikePostFinished(success, postId, newLikes, likedByMe, error);
                reply->deleteLater();
            });
    }

    void ServerHelper::recordSharePost(int postId) {
        QJsonObject data; // Empty body for this POST usually
        sendPostRequest(QString("/api/community/posts/%1/share").arg(postId), data,
            [this, postId](QNetworkReply *reply) {
                QString error;
                bool success = false;
                int newShares = 0;
                if (reply->error() == QNetworkReply::NoError) {
                    QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
                    QJsonObject json = doc.object();
                    if (json["code"].toInt() == 200) {
                        success = true;
                        QJsonObject dataObj = json["data"].toObject();
                        newShares = dataObj["shares_count"].toInt();
                    } else {
                        error = json["message"].toString();
                    }
                } else {
                    error = reply->errorString();
                }
                emit recordSharePostFinished(success, postId, newShares, error);
                reply->deleteLater();
            });
    }


    /*
     * 其他接口
     ***/

    void ServerHelper::sendPutRequest(const QString &path, const QJsonObject &data, std::function<void(QNetworkReply *)> callback)
    {
        QNetworkRequest request(QUrl(baseUrl + path));
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

        QJsonDocument doc(data);
        QNetworkReply *reply = manager->put(request, doc.toJson());
        connect(reply, &QNetworkReply::finished, this, [reply, callback]() {
            callback(reply);
        });
    }

    void ServerHelper::sendPostRequest(const QString &path, const QJsonObject &data, std::function<void(QNetworkReply *)> callback)
    {
        QNetworkRequest request(QUrl(baseUrl + path));
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

        QJsonDocument doc(data);
        QNetworkReply *reply = manager->post(request, doc.toJson());
        connect(reply, &QNetworkReply::finished, this, [reply, callback]() {
            callback(reply);
        });
    }

    void ServerHelper::sendGetRequest(const QString &path, const QUrlQuery &query, std::function<void(QNetworkReply *)> callback)
    {
        QUrl url(baseUrl + path);
        url.setQuery(query);
        QNetworkRequest request(url);

        QNetworkReply *reply = manager->get(request);
        connect(reply, &QNetworkReply::finished, this, [reply, callback]() {
            callback(reply);
        });
    }
}
